﻿using System;
using System.Web.UI;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Web.UI.WebControls;

namespace Marbles.Core.Content.Forms
{
    public class Question
    {
        public QuestionType QuestionType { get { return GetQuestionType(); } set { SetQuestionType(value); } }
        public string Text { get { return GetNodeInnerText("text"); } set { SetNodeInnerText("text", value); } }
        public string Id { get { return GetAttributeValue(_node, "id"); } set { SetAttributeValue(_node, "id", value); } }
        public Dimensions Dimensions { get { return GetDimensions(); } set { SetDimensions(value); } }
        public Dictionary<string, string> Items { get { return GetItems(); } set { SetItems(value); } }
        internal XmlNode InnerNode { get { return _node; } }

        private XmlNode _node = null;
        private XmlDocument _parent = null;

        public Question(XmlDocument parent, XmlNode node)
        {
            _parent = parent;
            _node = node;
            ValidateNode(parent);
        }

        public static Question CreateNew(XmlDocument document, string id)
        {
            XmlNode node = document.CreateElement("question");
            XmlNodeList root = document.GetElementsByTagName("questions");

            if (root.Count > 0)
            {
                root[0].AppendChild(node);
            }

            Question q = new Question(document, node);
            q.Id = id;
            return q;
        }

        private void CreateAttribute(XmlDocument document, XmlNode node, string name, string value)
        {
            if (node.Attributes[name] == null)
            {
                XmlAttribute attrib = document.CreateAttribute(name);
                attrib.Value = value;
                node.Attributes.Append(attrib);
            }
        }

        private void CreateNode(XmlDocument document, XmlNode parent, string name)
        {
            bool fnd = false;

            foreach (XmlNode node in parent.ChildNodes)
            {
                if (node.Name == name) { fnd = true; break; }
            }

            if (!fnd)
            {
                XmlNode child = document.CreateElement(name);
                parent.AppendChild(child);
            }
        }

        private void CreateDimensions(XmlDocument document, XmlNode parent)
        {
            XmlNode node = document.CreateElement("dimensions");
            CreateAttribute(document, node, "width", "");
            CreateAttribute(document, node, "height", "");
            CreateAttribute(document, node, "maxlength", "");
            parent.AppendChild(node);
        }

        private void ValidateNode(XmlDocument document)
        {
            CreateAttribute(document, _node, "id", "");
            CreateAttribute(document, _node, "type", QuestionType.SingleLineTextbox.ToString().ToLower());
            CreateNode(document, _node, "text");
            CreateNode(document, _node, "items");
            CreateDimensions(document, _node);
        }

        private QuestionType GetQuestionType()
        {
            string value = GetAttributeValue(_node, "type");

            if (!string.IsNullOrEmpty(value))
            {
                foreach (string key in Enum.GetNames(typeof(QuestionType)))
                {
                    if (key.ToLower() == value.ToLower())
                    {                        
                        return (QuestionType)Enum.Parse(typeof(QuestionType), key);
                    }
                }
                
            }

            return QuestionType.SingleLineTextbox;
        }

        private void SetQuestionType(QuestionType value)
        {
            SetAttributeValue(_node, "type", value.ToString().ToLower());
        }

        private void SetAttributeValue(XmlNode parent, string name, string value)
        {
            XmlAttribute attrib = parent.Attributes[name];
            if (attrib != null)
            {
                parent.Attributes[name].InnerText = value;
            }
        }

        private string GetAttributeValue(XmlNode parent, string name)
        {
            XmlAttribute attrib = parent.Attributes[name];

            if (attrib != null)
            {
                return attrib.Value;
            }
            return "";
        }


        private XmlNode FindNodeByName(string name)
        {
            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == name) { return node; }
            }
            return null;
        }

        private string GetNodeInnerText(string name)
        {
            XmlNode node = FindNodeByName(name);            
            return (node == null ? "" : node.InnerText);
        }

        private void SetNodeInnerText(string name, string value)
        {
            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == name) { node.InnerText = value; break; }
            }
        }

        private Dimensions GetDimensions()
        {
            Dimensions value = new Dimensions();
            string text = string.Empty;

            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == "dimensions")
                {
                    text = GetAttributeValue(node, "width");
                    if (!string.IsNullOrEmpty(text)) { value.Width = new System.Web.UI.WebControls.Unit(text); }
                    text = GetAttributeValue(node, "height");
                    if (!string.IsNullOrEmpty(text)) { value.Height = new System.Web.UI.WebControls.Unit(text); }
                    text = GetAttributeValue(node, "maxlength");
                    if (!string.IsNullOrEmpty(text))
                    {
                        Int32 i = 0;
                        if (!Int32.TryParse(text, out i)) { i = 0; }
                        value.MaxLength = i;
                    }
                    return value;
                }
            }

            return value;
        }

        private void SetDimensions(Dimensions value)
        {
            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == "dimensions")
                {
                    if (value.Width.IsEmpty) { SetAttributeValue(node, "width", ""); } else { SetAttributeValue(node, "width", value.Width.ToString()); }
                    if (value.Height.IsEmpty) { SetAttributeValue(node, "height", ""); } else { SetAttributeValue(node, "height", value.Height.ToString()); }
                    if (value.MaxLength == 0) { SetAttributeValue(node, "maxlength", ""); } else { SetAttributeValue(node, "maxlength", value.MaxLength.ToString()); }
                    break;
                }
            }
        }

        private Dictionary<string, string> GetItems()
        {
            Dictionary<string, string> items = new Dictionary<string, string>();
            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == "items")
                {
                    foreach (XmlNode child in node.ChildNodes)
                    {
                        items.Add(GetAttributeValue(child, "value"), GetAttributeValue(child, "text"));
                    }
                    return items;
                }
            }

            return items;
        }

        private void SetItems(Dictionary<string, string> value)
        {

            foreach (XmlNode node in _node.ChildNodes)
            {
                if (node.Name == "items")
                {
                    node.RemoveAll();
                    foreach (string key in value.Keys)
                    {
                        XmlNode child = _parent.CreateElement("item");
                        CreateAttribute(_parent, child, "value", key);
                        CreateAttribute(_parent, child, "text", Items[key]);
                        node.AppendChild(child);
                    }
                }
            }
        }

        public WebControl GetWebControl()
        {
            switch (QuestionType)
            {
                case Forms.QuestionType.Checkbox:
                    return CreateCheckBox();
                case Forms.QuestionType.CheckboxList:
                    return CreateCheckBoxList();
                case Forms.QuestionType.DropdownList:
                    return CreateDropDownList();
                case Forms.QuestionType.Listbox:
                    return CreateListBox(false);
                case Forms.QuestionType.MultiSelectListbox:
                    return CreateListBox(true);
                case Forms.QuestionType.MultiLineTextbox:
                    return CreateMultiLineTextbox();
                case Forms.QuestionType.RadioButton:
                    return CreateRadioButton();
                case Forms.QuestionType.RadioButtonList:
                    return CreateRadioButtonList();
                case Forms.QuestionType.SingleLineTextbox:
                    return CreateSingleLineTextbox();
                case Forms.QuestionType.PasswordTextbox:
                    return CreatePasswordTextbox();
            }

            return null;
        }

        private CheckBox CreateCheckBox()
        {
            CheckBox ctl = new CheckBox();
            ctl.ID = this.Id;
            ctl.Attributes["value"] = "true";
            return ctl;
        }

        private void AddListItems(ListItemCollection items)
        {
            items.Clear();
            foreach (string key in this.Items.Keys)
            {
                items.Add(new ListItem(Items[key], key));
            }
        }

        private CheckBoxList CreateCheckBoxList()
        {
            CheckBoxList ctl = new CheckBoxList();
            ctl.ID = this.Id;
            AddListItems(ctl.Items);
            return ctl;
        }

        private DropDownList CreateDropDownList()
        {
            DropDownList ctl = new DropDownList();
            ctl.ID = this.Id;
            if (!this.Dimensions.Width.IsEmpty) { ctl.Width = this.Dimensions.Width; }
            if (!this.Dimensions.Height.IsEmpty) { ctl.Height = this.Dimensions.Height; }
            AddListItems(ctl.Items);
            return ctl;
        }

        private ListBox CreateListBox(bool multiselect)
        {
            ListBox ctl = new ListBox();
            ctl.ID = this.Id;
            ctl.SelectionMode = (multiselect ? ListSelectionMode.Multiple : ListSelectionMode.Single);
            if (!this.Dimensions.Width.IsEmpty) { ctl.Width = this.Dimensions.Width; }
            if (!this.Dimensions.Height.IsEmpty) { ctl.Height = this.Dimensions.Height; }
            AddListItems(ctl.Items);
            return ctl;
        }

        private TextBox CreateMultiLineTextbox()
        {
            TextBox ctl = new TextBox();
            ctl.ID = this.Id;
            if (this.Dimensions.MaxLength > 0) { ctl.MaxLength = this.Dimensions.MaxLength; }
            if (!this.Dimensions.Width.IsEmpty) { ctl.Width = this.Dimensions.Width; }
            if (!this.Dimensions.Height.IsEmpty) { ctl.Height = this.Dimensions.Height; }
            ctl.TextMode = TextBoxMode.MultiLine;
            return ctl;
        }

        private RadioButton CreateRadioButton()
        {
            RadioButton ctl = new RadioButton();
            ctl.ID = this.Id;
            return ctl;
        }

        private RadioButtonList CreateRadioButtonList()
        {
            RadioButtonList ctl = new RadioButtonList();
            ctl.ID = this.Id;
            AddListItems(ctl.Items);
            return ctl;
        }

        private TextBox CreateSingleLineTextbox()
        {
            TextBox ctl = new TextBox();
            ctl.ID = this.Id;
            if (this.Dimensions.MaxLength > 0) { ctl.MaxLength = this.Dimensions.MaxLength; }
            if (!this.Dimensions.Width.IsEmpty) { ctl.Width = this.Dimensions.Width; }
            if (!this.Dimensions.Height.IsEmpty) { ctl.Height = this.Dimensions.Height; }
            ctl.TextMode = TextBoxMode.SingleLine;
            return ctl;
        }

        private TextBox CreatePasswordTextbox()
        {
            TextBox ctl = new TextBox();
            ctl.ID = this.Id;
            if (this.Dimensions.MaxLength > 0) { ctl.MaxLength = this.Dimensions.MaxLength; }
            if (!this.Dimensions.Width.IsEmpty) { ctl.Width = this.Dimensions.Width; }
            if (!this.Dimensions.Height.IsEmpty) { ctl.Height = this.Dimensions.Height; }
            ctl.TextMode = TextBoxMode.Password;
            return ctl;
        }

    }

    public enum QuestionType
    {
        DropdownList,
        Checkbox,
        CheckboxList,
        Listbox,
        MultiSelectListbox,
        SingleLineTextbox,
        MultiLineTextbox,
        RadioButton,
        RadioButtonList,
        PasswordTextbox
    }
}